package com.fanyue.modules.face.config;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.arcsoft.face.*;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import com.fanyue.core.exception.CoolException;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.io.File;
import java.util.Date;
import java.util.Map;

@Slf4j
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(ArcsoftProperties.class)
public class FaceEngineCenter {

	/*@Value("${project.directory}")
	private static String directory;*/

	private final Environment environment;
	private final ArcsoftProperties arcsoftProperties;
	private static FaceEngineCenter faceEngineCenter;

	// private static final Map<Long, FaceEngine> faceEngineConfigCenter = Maps.newHashMap();
	private static Map<String, FaceEngine> faceEngineConfigCenter = MapUtil.newHashMap();

	@PostConstruct
	public void init(){
		faceEngineCenter = this;
	}

	public static FaceEngine getFaceEngine() {
		String appName = faceEngineCenter.arcsoftProperties.getAppName();
		// String tenantId = AuthUtil.getTenantId();
		if (!faceEngineConfigCenter.isEmpty() && faceEngineConfigCenter.containsKey(appName)) {
			return faceEngineConfigCenter.get(appName);
		}
		FaceEngine faceEngine = initFaceEngine();
		VersionInfo versionInfo = faceEngine.getVersion();
		versionInfo.setVersion(appName + "-" + DateUtil.formatDateTime(new Date()));
		faceEngineConfigCenter.put(appName, faceEngine);
		return faceEngine;
	}

	public static FaceEngine initFaceEngine() {
		String directory = faceEngineCenter.arcsoftProperties.getDirectory();
		String authorizationMode = faceEngineCenter.arcsoftProperties.getAuthorizationMode();
		String appId = faceEngineCenter.arcsoftProperties.getAppId();
		String sdkKey = faceEngineCenter.arcsoftProperties.getSdkKey();
		String activeKey = faceEngineCenter.arcsoftProperties.getActiveKey();
		if (ObjectUtil.isEmpty(appId)) {
			throw new IllegalArgumentException("未找到对应人脸APPID的配置，请核实！");
		}
		if (ObjectUtil.isEmpty(sdkKey)) {
			throw new IllegalArgumentException(String.format("未找到对应人脸SDKKEY的配置，请核实！"));
		}
		// 判断环境
		String libPath = directory + "/face/lib";
		String authPath = directory + "/face/auth";
		boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");
		if (isWindows) {
			libPath = "D:\\Env\\Arcsoft\\lib";
			authPath = "D:\\Env\\Arcsoft\\auth";
		}

		FaceEngine faceEngine = new FaceEngine(libPath);
		// 激活引擎
		// int errorCode = faceEngine.activeOnline(appIdConfigure.getConVal(), sdkKeyConfigure.getConVal());

		// 判断是在线还是离线激活
		int activeCode = -1;
		if (authorizationMode.equals("online")) {
			activeCode = faceEngine.activeOnline(
					appId,
					sdkKey,
					activeKey
			);
		} else {
			// 判断是否有离线文件
			String devicesInfo = authPath + File.separator + "devicesInfo.txt";
			if (!FileUtil.exist(devicesInfo)) {
				ActiveDeviceInfo activeDeviceInfo = new ActiveDeviceInfo();
				activeCode = faceEngine.getActiveDeviceInfo(activeDeviceInfo);
				log.info("获取设备信息状态码：{}", activeCode);
				log.info("设备信息：{}", activeDeviceInfo.getDeviceInfo());
				// FileUtil.newFile(devicesInfo);
				FileUtil.appendUtf8String(activeDeviceInfo.getDeviceInfo(), devicesInfo);
				throw new CoolException("已成功生成离线激活设备文件，请联系管理员进行离线激活配置");
			} else {
				authPath = authPath + File.separator + "ArcFacePro64.dat";
				if (!FileUtil.exist(authPath)) {
					throw new CoolException("未检测到离线激活文件，请添加，目录为：" + authPath);
				}
				activeCode = faceEngine.activeOffline(authPath);
			}
		}

		log.info("引擎激活状态码：{}", activeCode);

		if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
			log.info("引擎激活失败");
		}

		ActiveDeviceInfo activeDeviceInfo = new ActiveDeviceInfo();
		// 采集设备信息（可离线）
		activeCode = faceEngine.getActiveDeviceInfo(activeDeviceInfo);
		log.info("采集设备信息状态码Code: {}", activeCode);
		log.info("设备信息: {}", activeDeviceInfo.getDeviceInfo());

		ActiveFileInfo activeFileInfo = new ActiveFileInfo();
		activeCode = faceEngine.getActiveFileInfo(activeFileInfo);
		if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
			log.info("获取激活文件信息失败");
		}

		// 引擎配置
		EngineConfiguration engineConfiguration = new EngineConfiguration();
		engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
		engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
		engineConfiguration.setDetectFaceMaxNum(10);
		// engineConfiguration.setDetectFaceScaleVal(16);
		// 功能配置
		FunctionConfiguration functionConfiguration = new FunctionConfiguration();
		functionConfiguration.setSupportAge(true);
		// functionConfiguration.setSupportFace3dAngle(true);
		functionConfiguration.setSupportFaceDetect(true);
		functionConfiguration.setSupportFaceRecognition(true);
		functionConfiguration.setSupportGender(true);
		functionConfiguration.setSupportLiveness(true);
		functionConfiguration.setSupportIRLiveness(true);
		functionConfiguration.setSupportImageQuality(true);
		functionConfiguration.setSupportMaskDetect(true);
		// functionConfiguration.setSupportUpdateFaceData(true);
		engineConfiguration.setFunctionConfiguration(functionConfiguration);

		// 初始化引擎
		activeCode = faceEngine.init(engineConfiguration);
		if (activeCode != ErrorInfo.MOK.getValue()) {
			log.info("初始化引擎失败");
		}
		VersionInfo version = faceEngine.getVersion();
		log.info("当前人脸检测版本：{}", version);

		return faceEngine;
	}

}
